CHAPTER 5: Jumps and branching
  You should know a little about how instructions are processed by processor. It
  fetches instruction in machine code, executes it, and then moves to next
  instruction. This is repeaten until instruction "int 20h" is reached. In this
  chapter we will learn something about instructions which changes this
  behavior.

  <from here i am using other form of label defintion - not "label name", but
  "name:". Look at chapter 3.2 if you forget about this.>

CHAPTER 5.1: instruction pointer
  Processor loads first instructions (it determines number of bytes the
  instrution consists from), executes it and then moves to another instruction.
  But how this mechanism works? Processor has a special word register "ip" which
  holds address of currently executed instruction. After instruction is executed
  processor adds it's size to "ip" and executes instruction on address in "ip".
  Mechanism works like this:
    Loop 
      Execute instruction on "ip"
      size = size of instruction on "ip"
      ip = ip + size
    Until instruction "int 20h" is found

  NOTE: as with others pointers, "ip" doesn't hold full address of instruction,
  only offset part. Be we don't care about this now.

  NOTE: "ip" stands for "instruction pointer"

  <TODO - some examples about "ip">

CHAPTER 5.2: Jumps
  Register "ip" is not like other registers (like "ax","ah","bp"...). It's
  contents can't be changed using "mov" instruction. "mov ip,5" doesn't work.
  But there is a special instruction which can change value in "ip" register. It
  is "jmp" ("jmp" = "jump") instruction. This instruction has one operand, new
  address for "ip" register.  So "jmp 5" has effect like "mov ip,5" would if it
  were an instruction.  Example:
    org 256
    jmp Start

    text db 'Text to output'

    Start:
    mov ah,9
    mov dx,text
    int 21h
    int 20h
  First instruction sets value of "ip" to address of "mov ah,9" instruction
  (address is held in label "Start"). Thus processor won't try to execute bytes
  defined by "Text to output" string and this program will work.

  NOTE: of course, when "ip" is changed by "jmp" instruction, then size of this
  instruction is NOT added to it.

CHAPTER 5.3: Comparing and conditonal jumps
  If you can code any language already you should know branching, eg.
  conditional execution of some parts of code. For example: say you want value
  lesser than 10 in "al". So if value in "al" register is >= 10, you will set
  "al" to 10. This is branching - if some condition is true then something is
  executed, otherwise it is not executed. Assembly impletation of this mechanism
  is that when condition is false you will jump over conditional code, when
  condition is true you will just cotinue execution. It is as if C code:
    if (condition)
      ConditionalCode(); //this can be any C code, not just function call
  would be writen this way:
    if (!condition) goto LabelAfterConditionalCode;
    ConditionalCode(); //this can be any C code, not just function call
    LabelAfterConditionalCode:
  
  First problem is how to decide whether condition is true. In assembly, there
  is instruction which can compare two operands. It is "cmp". It's operands
  follow same rules as "mov"'s operands (almost every instruction follows these
  or very similar rules). So examples of comparing:
    cmp ax,bx  	                  - compare value of "ax" to value of "bx"
    cmp al,byte [SomeLabel]       - comapre value of "al" to byte at SomeLabel
    cmp ax,5                      - compare value of "ax" to 5
    cmp ax,al	                  - wrong, operands have different size
  This instructions checks whether first operand is same, greater or lesser than
  second.

  >>> instruction: cmp

  OK, we can compare, but how are results of comparison stored? CPU (processor)
  has special register called "flags register" in which it stores results of
  camparison (and some other things too). This register can't be accessed with
  "mov" or similar instructions (same like "ip"), it's value is set by "cmp"
  instruction. Now you don't have to care HOW is result of comparison stored in
  this register, you would need understand bit arithmetics.

  >>> term+register: flags

  OK, we can compare, we know result is stored in "flags". Only thing we need
  now is conditional jump itslef. Conditional jump is jump which is taken only
  when condition specified by you is true (in flags register). It will be best
  explained on example. We compare "ax" to "bx" ("cmp ax,bx"). Now conditional
  jump can jump if "ax" < "bx", or when "ax" = "bx", or when "ax" >= "bx" etc.
  These jumps are (op1 is first operand of "cmp", op2 is second):
    je     - jump if op1 = op2 (op1 is "equal to" op2)
    ja     - jump if op1 > op2 (op1 is "above" op2)
    jb     - jump if op1 < op2 (op1 is "below" op2)
    jae    - jump if op1 >= op2 (op1 is "above or equal to" op2)
    jbe    - jump if op1 <= op2 (op1 is "below or equal to" op2)

  >>> term: conditional jumps
  >>> + all these instructions

  Example code: (but don't try to compile it, it is not .COM executable, it is 
                 just piece of code)
    cmp ax,10
    jbe AX_lesser_than_10
    mov ax,10
    AX_lesser_than_10:
  this piece of code will check whether value in "ax" is below or equal to 10, 
  and if not (if the value in "ax" is above 10) it will set "ax" to 10.
  Corresponding C code is:
    if (ax>10) ax=10;
  or more similar to our assembly version:
    if (ax <= 10) goto AX_lesser_than_10
    ax=10;
    AX_lesser_than_10:
  
  Another example: get maximum of {ax,bx} and store it in ax:
    cmp ax,bx
    jae AX_already_contains_bigger_value
    mov ax,bx
    AX_already_contains_bigger_value:
  So compare "ax" to "bx", if it is bigger or equal then it already contains the
  bigger value, we dont need to change anything. If "ax" is lesser than "bx"
  then we must move value in "bx" (=bigger value) to "ax".

  More complicated version: store maximum of {ax,bx} in cx:
    cmp ax,bx
    ja  AX_bigger
    mov cx,bx
    jmp done
    AX_bigger
    mov cx,ax
    done:
  so we compare "ax" to "bx", then if "ax" is lesser than "bx" jump won't be
  taken and we continue by "mov cx,bx" which stores bigger value in "cx" as
  wanted, and then "jmp done" skips instructions used in case "ax" is bigger. If
  "ax" is bigger than "bx", then "jmp AX_bigger" will be taked, so next
  instruction is "mov cx,ax" which moves greater value (in "ax") to "cx". You
  see, code was divided into two "branches" one for ax>bx, other for ax<=bx.
  Finally both branches goes to instruction behind "done:", and at this place
  "cx" always holds bigger value.  By the way, there could be "jae" instead "ja",
  because for case when ax=bx both branches have same effect.

  But what can we do if we to jump when operands are NOT equal? We could do
  something like this:
    cmp ax,bx
    je Same
    jmp NotSame
    Same:
    ...
    NotSame:
  but this is not needed because there are instruction which jumps when
  condition is not true. These are "jne","jna","jnb","jnae","jnbe". "jne" jumps
  when operands are not equal, "jna" when first operand is not above second
  operand etc., so:
    cmp ax,bx
    jne NotSame:
    ...
    NotSame:
  and ... part is executed only if value in ax is not equal to value in bx.

  >>> these 5 instructions

  NOTE: "jna" is same as "jbe", "jnb" is same as "jae", "jb" is same as "jnae"
  "ja" is same as "jnbe".

  IMPORTANT NOTE: many instruction change "flags" register, not only "cmp", so
  conditional jump should be right behind "cmp", no instructions between them.
